//
//  NSDictionary+HTTP.m
//  CocoaSMS
//
//  Created by Sooyong Wang on 09. 01. 31.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "NSDictionary+HTTP.h"

@implementation NSDictionary ( CurlHTTPExtensions )

/*"	This category adds methods for dealing with HTTP input and output to an #NSDictionary.
 "*/

/*"	Convert a dictionary to an HTTP-formatted string with 7-bit ASCII encoding;
 see #formatForHTTPUsingEncoding.
 "*/

- (NSString *) formatForHTTP
{
	return [self formatForHTTPUsingEncoding:NSASCIIStringEncoding];
	// default to dumb ASCII only
}

/*"	Convert a dictionary to an HTTP-formatted string with the given encoding.
 Spaces are turned into !{+}; other special characters are escaped with !{%};
 keys and values are output as %{key}=%{value}; in between arguments is !{&}.
 "*/

- (NSString *) formatForHTTPUsingEncoding:(NSStringEncoding)inEncoding
{
	return [self formatForHTTPUsingEncoding:inEncoding ordering:nil];
}

/*"	Convert a dictionary to an HTTP-formatted string with the given encoding, as above.
 The inOrdering parameter specifies the order to place the inputs, for servers that care about this.
 (Note that keys in the dictionary that aren't in inOrdering will not be included.)
 If inOrdering is nil, all keys and values will be output in an unspecified order.
 "*/

- (NSString *) formatForHTTPUsingEncoding:(NSStringEncoding)inEncoding ordering:(NSArray *)inOrdering
{
	NSMutableString *s = [NSMutableString stringWithCapacity:256];
	NSEnumerator *e = (nil == inOrdering) ? [self keyEnumerator] : [inOrdering objectEnumerator];
	id key;
	CFStringEncoding cfStrEnc = CFStringConvertNSStringEncodingToEncoding(inEncoding);
	
	while ((key = [e nextObject]))
	{
		id keyObject = [self objectForKey: key];
		// conform with rfc 1738 3.3, also escape URL-like characters that might be in the parameters
		NSString *escapedKey
		= (NSString *) CFURLCreateStringByAddingPercentEscapes(
																													 NULL, (CFStringRef) key, NULL, (CFStringRef) @";:@&=/+", cfStrEnc);
		if ([keyObject respondsToSelector: @selector(objectEnumerator)])
		{
			NSEnumerator	*multipleValueEnum = [keyObject objectEnumerator];
			id				aValue;
			
			while ((aValue = [multipleValueEnum nextObject]))
			{
				NSString *escapedObject
				= (NSString *) CFURLCreateStringByAddingPercentEscapes(
																															 NULL, (CFStringRef) [aValue description], NULL, (CFStringRef) @";:@&=/+", cfStrEnc);
				[s appendFormat:@"%@=%@&", escapedKey, escapedObject];
			}
		}
		else
		{
			NSString *escapedObject
			= (NSString *) CFURLCreateStringByAddingPercentEscapes(
																														 NULL, (CFStringRef) [keyObject description], NULL, (CFStringRef) @";:@&=/+", cfStrEnc);
			[s appendFormat:@"%@=%@&", escapedKey, escapedObject];
		}
	}
	// Delete final & from the string
	if (![s isEqualToString:@""])
	{
		[s deleteCharactersInRange:NSMakeRange([s length]-1, 1)];
	}
	return s;	
}

@end
